WaitTime, ModelName, and AIProviderType look like enums -- GPAL.WithWaitFor(WaitTime.Forever), .WithModel(ModelName.ClaudeSonnet46), .WithProvider(AIProviderType.Anthropic). But they are actually small readonly structs with an implicit conversion from a plain value, so any string or number you type by hand works too. It is a pattern most C# developers have never needed, because most APIs do not face this exact problem.
GPALFile, GPALUrl, GPALGrid, and GPALDatabase show up everywhere a typical API would hand you a raw string, path, or array. GPAL gives you an object instead. And that object carries real behavior the library uses directly.
Selectors are how GPAL locates elements in a browser or desktop application. A single selector can define multiple location strategies. If the first finds nothing, GPAL automatically tries the next.
After a location strategy finds candidate elements, match criteria filter that set to only the elements you actually want. This two-layer approach. Find then filter, is specific to browser automation and keeps selectors both broad and precise.
Selectors find elements - actions are what GPAL actually does to them. Clicking, typing, hovering, scraping into a grid, filling from a data source, and waiting are all actions, and every action runs against everything the current selectors matched.
GPAL settings flow from broad to specific. Configure once globally and override only where needed. At the browser or application object level, or at the individual selector level.
GPAL has four branching points: CallIfFound and CallIfNotFound respond to element discovery, WithStopOnNotFound terminates the workflow when an element is missing, and CallAfterFillIn branches per row during data-driven fill operations. CallIfFound and CallIfNotFound follow a three-scope cascade -- selector, UOW, and global. CallAfterFillIn is a single per-UOW delegate where only Terminate has a defined effect.
MatchFunction, CallIfFound, CallIfNotFound, and CallAfterFillIn all return a CallIfStatus value that tells GPAL what to do next. The same four values appear in every callback, but their precise effect depends on which callback you are in.
GPAL never writes files or logs anything on its own. Every operation publishes a structured event, and what you attach to those events decides where they go. A console, the debugger, a handler of your own, or a logger.
The Event System says GPAL never writes logs on its own. GPAL.Logger is the built-in, opt-in place for events to land. One fluent chain configures where entries go and in what format, and from then on every event published anywhere in the workflow writes one more entry there.
GPALElement.Click() handles most callback interactions. ElementAssistant is for the cases where it can't. Switching to JavaScript or hardware interaction when Selenium clicks are intercepted, downloading or uploading via a found element, or filling text into an input element your selector already located.
A persistent selector is checked on every unit of work for the life of the session. Use it for things that can pop up at any time and aren't part of the workflow itself, like cookie-consent banners or session-timeout dialogs.
When a Selenium action throws, GPAL does not just give up. It logs an EXCEPTION event and retries the action, usually via JavaScript injection, so the workflow keeps moving. WithNoFallbackActions(true) turns this safety net off for workflows that should fail loudly at the first sign of trouble.
One fluent API retrieves credentials whether typed directly, stored in a password manager vault, or obtained via an OAuth/service-account/API-key flow. The consuming code stays the same.
CredentialServiceType.StaticKey is a simpler credential type for services that authenticate with one static API key. Supply the key via WithServiceKey, WithKeyFromEnv, or WithKeyFromApi. FetchAccessToken hands it back unchanged with no login step.